﻿using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Castle.Core.Logging;
using DevM.Development.Projects;
using DevM.Development.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DevM.Development.ReleaseRecords
{
    public class ReleaseRecordManager : ITransientDependency, IDomainService
    {
        private readonly ILogger logger;
        private readonly ResourceManager resourceManager;
        private readonly IRepository<ReleaseRecord, long> releaseRecordRepository;
        private readonly IRepository<Feedback, long> feedbackRepository;
        private readonly IRepository<ReleaseLog, long> releaseLogRepository;
        private readonly ProjectStore projectStore;

        public ReleaseRecordManager(ILogger logger, ResourceManager resourceManager, IRepository<ReleaseRecord, long> releaseRecordRepository, IRepository<Feedback, long> feedbackRepository, IRepository<ReleaseLog, long> releaseLogRepository, ProjectStore projectStore)
        {
            this.logger = logger;
            this.resourceManager = resourceManager;
            this.releaseRecordRepository = releaseRecordRepository;
            this.feedbackRepository = feedbackRepository;
            this.releaseLogRepository = releaseLogRepository;
            this.projectStore = projectStore;
        }
        /// <summary>
        /// 发布项目列表
        /// </summary>
        public IQueryable<ReleaseRecord> ReleaseRecords { get => releaseRecordRepository.GetAll(); }
        /// <summary>
        /// 发布日志
        /// </summary>
        public IQueryable<ReleaseLog> ReleaseLogs { get => releaseLogRepository.GetAll(); }
        /// <summary>
        /// 反馈
        /// </summary>
        public IQueryable<Feedback> Feedbacks { get => feedbackRepository.GetAll(); }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="releaseRecordId"></param>
        /// <param name="environmentId"></param>
        /// <param name="releaseLog"></param>
        /// <returns></returns>
        public async Task<ReleaseLog> Release(ReleaseLog releaseLog)
        {
            var record = await releaseRecordRepository.GetAsync(releaseLog.ReleaseRecordId);
            if (record == null) return null;
            var preRecord = releaseRecordRepository.GetAll().Where(r => r.ProjectId == record.ProjectId && r.Id < record.Id).OrderByDescending(r=>r.Id).FirstOrDefault();
            var environments = await projectStore.GetEnvironmentsByProjectId(record.ProjectId);
            //如果当前record的最新发布环境大于前一次，则不允许发布
            if (preRecord != null && environments.IndexOf(
                environments.Where(e => e.Id == preRecord.CurrentEnvironmentId).FirstOrDefault())
                < environments.IndexOf(environments.Where(e => e.Id == releaseLog.ReleaseEnvironmentId).FirstOrDefault()))
                throw new Abp.AbpException("CurrentEnvironment has not release in previous");

            record.HasReleased = true;
            record.CurrentEnvironmentId = releaseLog.ReleaseEnvironmentId;
            record.LastModificationTime = DateTime.Now;
            record.LastModifierUserId = releaseLog.CreatorUserId;
            await releaseRecordRepository.UpdateAsync(record);
            //如果是第一个反馈的发布则插入一条未发布的
            if(environments.FirstOrDefault()!=null&& environments.FirstOrDefault().Id== releaseLog.ReleaseEnvironmentId)
            {
                await AddReleaseRecordAsync(record.ProjectId, releaseLog.CreatorUserId??0, record.TenantId);
            }
            return await releaseLogRepository.InsertAsync(releaseLog); 
        }

        /// <summary>
        /// 新增发布记录
        /// </summary>
        /// <returns></returns>
        public async Task<ReleaseRecord> AddReleaseRecordAsync(long projectId,long creatorUserId,int? tenantId)
        {
            return await releaseRecordRepository.InsertAsync(new ReleaseRecord
            {
                ProjectId = projectId,
                TenantId = tenantId,
                CreationTime = DateTime.Now,
                CreatorUserId = creatorUserId
            });
        }
        /// <summary>
        /// 新增发布记录
        /// </summary>
        /// <returns></returns>
        public ReleaseRecord AddReleaseRecord(long projectId, long creatorUserId, int? tenantId)
        {
            return releaseRecordRepository.Insert(new ReleaseRecord
            {
                ProjectId = projectId,
                TenantId = tenantId,
                CreationTime = DateTime.Now,
                CreatorUserId = creatorUserId
            });
        }

        /// <summary>
        /// 添加反馈
        /// </summary>
        /// <param name="feedback"></param>
        /// <returns></returns>
        public async Task<Feedback> AddFeedback(Feedback feedback)
        {
            feedback.CreationTime = DateTime.Now;
            var id = await feedbackRepository.InsertAndGetIdAsync(feedback);
            return await feedbackRepository.GetAsync(id);
        }
        /// <summary>
        /// 更新项目反馈
        /// </summary>
        /// <param name="modifierUserId"></param>
        /// <param name="feedback"></param>
        /// <returns></returns>
        public async Task<Feedback> UpdateFeedback(Feedback feedback)
        {
            var _feedback = await feedbackRepository.GetAsync(feedback.Id);
            _feedback.LastModificationTime = DateTime.Now;
            _feedback.LastModifierUserId = feedback.LastModifierUserId;
            _feedback.Path = feedback.Path;
            _feedback.Description = feedback.Description;
            _feedback.Memo = feedback.Memo;
            return await feedbackRepository.UpdateAsync(_feedback);
        }
        /// <summary>
        /// 删除反馈
        /// </summary>
        /// <param name="deleterUserId"></param>
        /// <param name="feedbackId"></param>
        /// <returns></returns>
        public async Task DeleteFeedback(params long[] feedbackId)
        {
            foreach (var id in feedbackId)
            {
                var feedback =await feedbackRepository.GetAsync(id);
                if (feedback.Status !=  Feedback.FeedbackStatus.Pending) continue;
                await feedbackRepository.DeleteAsync(id);
            }
        }
    }
}
